﻿using System;
using System.Text;

namespace Pay.Core {
	public class ClassHmac {
		// Fields
		private int chrsz = 8;
		private bool hexcase = false;

		// Methods
		private string binl2hex(int[] binarry) {
			string str = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
			string str2 = "";
			for (int i = 0; i < (binarry.Length * 4); i++) {
				str2 = str2 + str.Substring((binarry[i >> 2] >> (((i % 4) * 8) + 4)) & 15, 1) + str.Substring((binarry[i >> 2] >> ((i % 4) * 8)) & 15, 1);
			}
			return str2;
		}

		private int bit_rol(int num, int cnt) {
			if (num >= 0) {
				return ((num << cnt) | (num >> (0x20 - cnt)));
			}
			return ((num << cnt) | ((int)((0x100000000L + num) >> (0x20 - cnt))));
		}

		private int[] core_hmac_md5(string key, string data) {
			Encoding encoding = Encoding.GetEncoding("gb2312");
			int[] x = this.str2binl(key);
			int length = encoding.GetBytes(key).Length;
			if (x.Length > 0x10) {
				x = this.core_md5(x, length * this.chrsz);
			}
			x = this.IntUpper(x, 0x10);
			int[] numArray2 = new int[0x10];
			int[] numArray3 = new int[0x10];
			for (int i = 0; i < 0x10; i++) {
				numArray2[i] = x[i] ^ 0x36363636;
				numArray3[i] = x[i] ^ 0x5c5c5c5c;
			}
			byte[] bytes = encoding.GetBytes(data);
			int[] numArray4 = this.str2binl(data);
			numArray2 = this.IntUpper(numArray2, 0x10 + numArray4.Length);
			numArray4.CopyTo(numArray2, 0x10);
			int[] numArray5 = this.core_md5(numArray2, 0x200 + (bytes.Length * this.chrsz));
			numArray3 = this.IntUpper(numArray3, 0x10 + numArray5.Length);
			numArray5.CopyTo(numArray3, 0x10);
			return this.core_md5(numArray3, 640);
		}

		private int[] core_md5(int[] x, int len) {
			int[] numArray2;
			IntPtr ptr;
			x = this.IntUpper(x, (len >> 5) + 1);
			(numArray2 = x)[(int)(ptr = (IntPtr)(len >> 5))] = numArray2[(int)ptr] | (((int)0x80) << (len % 0x20));
			int num = len + 0x40;
			x = this.IntUpper(x, ((num >> 9) << 4) + 15);
			if (num >= 0) {
				x[((num >> 9) << 4) + 14] = len;
			} else {
				x[(int)((IntPtr)((ulong)(((0xffffffffL + num) >> 9) << 4) + ((ulong)14L)))] = len;
			}
			int a = 0x67452301;
			int b = -271733879;
			int c = -1732584194;
			int d = 0x10325476;
			for (int i = 0; i < x.Length; i += 0x10) {
				int y = a;
				int num8 = b;
				int num9 = c;
				int num10 = d;
				a = this.md5_ff(a, b, c, d, x[i], 7, -680876936);
				d = this.md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
				c = this.md5_ff(c, d, a, b, x[i + 2], 0x11, 0x242070db);
				b = this.md5_ff(b, c, d, a, x[i + 3], 0x16, -1044525330);
				a = this.md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
				d = this.md5_ff(d, a, b, c, x[i + 5], 12, 0x4787c62a);
				c = this.md5_ff(c, d, a, b, x[i + 6], 0x11, -1473231341);
				b = this.md5_ff(b, c, d, a, x[i + 7], 0x16, -45705983);
				a = this.md5_ff(a, b, c, d, x[i + 8], 7, 0x698098d8);
				d = this.md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
				c = this.md5_ff(c, d, a, b, x[i + 10], 0x11, -42063);
				b = this.md5_ff(b, c, d, a, x[i + 11], 0x16, -1990404162);
				a = this.md5_ff(a, b, c, d, x[i + 12], 7, 0x6b901122);
				d = this.md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
				c = this.md5_ff(c, d, a, b, x[i + 14], 0x11, -1502002290);
				x = this.IntUpper(x, i + 0x10);
				b = this.md5_ff(b, c, d, a, x[i + 15], 0x16, 0x49b40821);
				a = this.md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
				d = this.md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
				c = this.md5_gg(c, d, a, b, x[i + 11], 14, 0x265e5a51);
				b = this.md5_gg(b, c, d, a, x[i], 20, -373897302);
				a = this.md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
				d = this.md5_gg(d, a, b, c, x[i + 10], 9, 0x2441453);
				c = this.md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
				b = this.md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
				a = this.md5_gg(a, b, c, d, x[i + 9], 5, 0x21e1cde6);
				d = this.md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
				c = this.md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
				b = this.md5_gg(b, c, d, a, x[i + 8], 20, 0x455a14ed);
				a = this.md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
				d = this.md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
				c = this.md5_gg(c, d, a, b, x[i + 7], 14, 0x676f02d9);
				b = this.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
				a = this.md5_hh(a, b, c, d, x[i + 5], 4, -378558);
				d = this.md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
				c = this.md5_hh(c, d, a, b, x[i + 11], 0x10, 0x6d9d6122);
				b = this.md5_hh(b, c, d, a, x[i + 14], 0x17, -35309556);
				a = this.md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
				d = this.md5_hh(d, a, b, c, x[i + 4], 11, 0x4bdecfa9);
				c = this.md5_hh(c, d, a, b, x[i + 7], 0x10, -155497632);
				b = this.md5_hh(b, c, d, a, x[i + 10], 0x17, -1094730640);
				a = this.md5_hh(a, b, c, d, x[i + 13], 4, 0x289b7ec6);
				d = this.md5_hh(d, a, b, c, x[i], 11, -358537222);
				c = this.md5_hh(c, d, a, b, x[i + 3], 0x10, -722521979);
				b = this.md5_hh(b, c, d, a, x[i + 6], 0x17, 0x4881d05);
				a = this.md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
				d = this.md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
				c = this.md5_hh(c, d, a, b, x[i + 15], 0x10, 0x1fa27cf8);
				b = this.md5_hh(b, c, d, a, x[i + 2], 0x17, -995338651);
				a = this.md5_ii(a, b, c, d, x[i], 6, -198630844);
				d = this.md5_ii(d, a, b, c, x[i + 7], 10, 0x432aff97);
				c = this.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
				b = this.md5_ii(b, c, d, a, x[i + 5], 0x15, -57434055);
				a = this.md5_ii(a, b, c, d, x[i + 12], 6, 0x655b59c3);
				d = this.md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
				c = this.md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
				b = this.md5_ii(b, c, d, a, x[i + 1], 0x15, -2054922799);
				a = this.md5_ii(a, b, c, d, x[i + 8], 6, 0x6fa87e4f);
				d = this.md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
				c = this.md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
				b = this.md5_ii(b, c, d, a, x[i + 13], 0x15, 0x4e0811a1);
				a = this.md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
				d = this.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
				c = this.md5_ii(c, d, a, b, x[i + 2], 15, 0x2ad7d2bb);
				b = this.md5_ii(b, c, d, a, x[i + 9], 0x15, -343485551);
				a = this.safe_add(a, y);
				b = this.safe_add(b, num8);
				c = this.safe_add(c, num9);
				d = this.safe_add(d, num10);
			}
			return new int[] { a, b, c, d };
		}

		public string hex_hmac_md5(string data, string key) {
			return this.binl2hex(this.core_hmac_md5(key, data));
		}

		private int[] IntUpper(int[] x, int len) {
			if (x.Length < len) {
				int[] array = new int[len];
				x.CopyTo(array, 0);
				x = array;
			}
			return x;
		}

		private int md5_cmn(int q, int a, int b, int x, int s, int t) {
			return this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b);
		}

		private int md5_ff(int a, int b, int c, int d, int x, int s, int t) {
			return this.md5_cmn((b & c) | (~b & d), a, b, x, s, t);
		}

		private int md5_gg(int a, int b, int c, int d, int x, int s, int t) {
			return this.md5_cmn((b & d) | (c & ~d), a, b, x, s, t);
		}

		private int md5_hh(int a, int b, int c, int d, int x, int s, int t) {
			return this.md5_cmn((b ^ c) ^ d, a, b, x, s, t);
		}

		private int md5_ii(int a, int b, int c, int d, int x, int s, int t) {
			return this.md5_cmn(c ^ (b | ~d), a, b, x, s, t);
		}

		private int safe_add(int x, int y) {
			int num = (x & 0xffff) + (y & 0xffff);
			int num2 = ((x >> 0x10) + (y >> 0x10)) + (num >> 0x10);
			return ((num2 << 0x10) | (num & 0xffff));
		}

		private int[] str2binl(string str) {
			int num = (((int)1) << this.chrsz) - 1;
			byte[] bytes = Encoding.GetEncoding("gb2312").GetBytes(str);
			int num2 = 0;
			if (((bytes.Length % 4) != 0) || (bytes.Length == 0)) {
				num2 = (bytes.Length / 4) + 1;
			} else {
				num2 = bytes.Length / 4;
			}
			int[] numArray = new int[num2];
			for (int i = 0; i < (bytes.Length * this.chrsz); i += this.chrsz) {
				IntPtr ptr;
				numArray[(int)(ptr = (IntPtr)(i >> 5))] = numArray[(int)ptr] | ((bytes[i / this.chrsz] & num) << (i % 0x20));
			}
			return numArray;
		}
	}
}
